import random
import re
import sys
import time
from collections import OrderedDict
from datetime import datetime
import pandas as pd
from lxml import etree
from splinter.browser import Browser

print('-----微博数据爬虫-------')
# 修改为微博登录信息时，登录时可以自动填充
username = '15177818542'
password = '12345..'

# 登陆
browser = None
browser_name = "chrome"  # 浏览器名
driver_path = "chromedriver.exe"  # 打开浏览器的驱动
base_url = "https://s.weibo.com/"  # 微博搜索主页
url = "https://weibo.com/login.php#_loginLayer_1636426106098"
browser = Browser(driver_name=browser_name, executable_path=driver_path)  # 打开浏览器 service_log_path='log.log'
browser.visit(url)  # 访问微博搜索页面
time.sleep(2)  # 暂停两秒，等待浏览器加载完成

print(".......请在打开的浏览器中登录........")
browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")  # 跳转到页面底部
#browser.click_link_by_text('登录')  # 点击登录按钮
# 填充用户名的密码
if username is not None:
    browser.fill("username", username)
if password is not None:
    browser.fill("password", password)
#点击登录
browser.find_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[6]/a').click()
#自行扫码登录微博

# 输入关键字、搜索时间等信息
key_word = input('请输入搜索关键字（输入q退出）：')
if key_word == 'q':
    print("正在退出....")
    sys.exit(0)
 
start_time = input('请输入开始时间（输入格式：2020-6-1-8 代表年-月-日-小时）：')
end_time = input('请输入结束时间---不输入默认为直至现在（输入格式：2020-6-2-8代表年-月-日-小时）：')
sleep_time = input('输入页面间的访问间隔时间(默认10秒)：')


#  通过构造的搜索 url，跳转到搜索结果页面
start_time = datetime.strptime(start_time, "%Y-%m-%d-%H").strftime("%Y-%m-%d-%H")
if end_time:
    end_time = datetime.strptime(end_time, "%Y-%m-%d-%H").strftime("%Y-%m-%d-%H")
else:
    end_time = datetime.now().strftime('%Y-%m-%d-%H')
   

#将搜索关键字放到搜索链接  
search_url = 'https://s.weibo.com/weibo/{keyword}' \
                  '&timescope=custom:{start_time}:{end_time}&refer=g'  # 搜索结果的url
#分别将用户选择的关键词、开始时间和结束时间，在微博搜索里面进行搜索
s_url = search_url.format(keyword=key_word, start_time=start_time, end_time=end_time)
            
#设置页面间的访问间隔时间，页面停留的时间
if not sleep_time:
    sleep_time = 10
else:
    sleep_time = int(sleep_time)

browser.visit(s_url) # 访问微博搜索页面，显示在浏览器中

print('.......爬取数据正在开始.......')

# 获取网页源代码，查找数据
page_count = 0  # 记录每个页面抓取的数据量
all_count = 0  # 记录抓取的数据总量
base_sava_path = ' '  # 输出文件的保存路径
save_file_name = key_word + start_time + "~" + end_time  # 输出文件名

save_data = OrderedDict({  # 保存抓取的数据
    "昵称": [],
    "微博正文": [],
    "微博链接": [],
    "时间": [],
    "收藏数": [],
    "转发数": [],
    "评论数": [],
    "点赞数": [],
    "设备": [],
    "图片": []
})

xpath_dict = {  # 解析数据用的 xpath 语法
    '昵称': '//div[@class="info"]//a[@class="name"]/text()',
    '微博正文': '//div[@class="content"]/p[@node-type="feed_list_content"]',
    '微博链接': '//div[@class="content"]/p[@class="from"]/a[1]/@href',
    '时间': '//div[@class="content"]/p[@class="from"]/a[1]/text()',
    '收藏数': '//a[@action-type="feed_list_favorite"]/text()',
    '转发数': '//a[@action-type="feed_list_forward"]/text()',
    '评论数': '//a[@action-type="feed_list_comment"]/text()',
    '点赞数': '//div[@class="card-act"]//a[@action-type="feed_list_like"]//em/text()',
    '设备': '//div[@class="content"]/p/a[@rel="nofollow"]/text()',
    '图片':'//div[@class="media media-piclist"]//li/img/@src'
    }


# 获取网页
browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")  # 跳转到页面底部

#获取时间
def get_date(str_time):
       """
       格式化传入的时间字符串
       """
       str_time = str_time.strip().replace(' ', '')

       if '今天' in str_time or '分钟前' in str_time or '秒前' in str_time:
           return datetime.now().date()

       str_time = re.findall(r"(.*\d\d月\d\d日).*", str_time)[0]  # 使用正则表达式找出时间

       if "年" not in str_time:
           now_year = datetime.now().year
           str_time = str(now_year) + "年" + str_time

       date = datetime.strptime(str_time, '%Y年%m月%d日')
       return date.date()

#获取评论数
def get_num(string):
        """
        用户获取评论数、点赞数等
        """
        number = re.findall(r"(\d+)", string)
        if number:
            return number[0]
        else:
            return '0'  #如果获取的评论数、点赞数是空值，就记为0


page_index = 1  # 记录页码

while page_index <= 2:  # 微博搜索结果最多为50页
    # 获取真实的页码
    real_page = re.findall(r'page=(\d+)', browser.url)
    
    print('正在抓取第%s页内容：' % page_index, end='')
    browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")  # 跳转到页面底部
    cards = browser.find_by_xpath('//div[@id="pl_feedlist_index"]')  # 获取所有的博文
    card = cards
    etree_html = etree.HTML(card.html)
    number = ['收藏数', '转发数', '评论数', '点赞数']
    
    for key in xpath_dict.keys():
        xpath = xpath_dict.get(key)
        data = etree_html.xpath(xpath)
        
       #保存数据
        if data:
            for i in range(len(data)):
                
                if key in number:
                    save_data[key].append(get_num(data[i]))  #这里的0改成i

                elif key == '时间':
                    save_data[key].append(get_date(data[i]).strftime('%Y-%m-%d'))

                elif key == '微博正文':
                    content = data[i].xpath('string()').replace(' ', '').replace('\n', '')
                    save_data[key].append(content)

                else: #获取key里面的其他因素
                    save_data[key].append(data[i])

        else:  #如果搜索到的key是空的就添加0进去，记为0
            if key in number:
                save_data[key].append('0')

            else:
                save_data[key].append('')
                
    print('本页已抓取数据，模拟等待中.....')
#    data = pd.DataFrame(save_data) 
#    file_path = base_sava_path + save_file_name + '.xlsx'
#
#    data.to_excel(file_path, index=False)  # 将数据保存到 excel
#    print('文件正在保存...', end='\n\n')    
   
  # 基于设置的休眠时间，随机设置一个休眠值---模拟人类浏览行为
    sleep_time = random.randint(sleep_time, sleep_time + 5)
    
    time.sleep(sleep_time)  # 模拟用户浏览网页的时间

    browser.click_link_by_text('下一页')  # 点击下一页
    page_index += 1


print('爬取完毕，谢谢等候！')
#browser.quit() #关闭浏览器

